package org.changs.aplug.base;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.trello.rxlifecycle2.android.FragmentEvent;
import com.trello.rxlifecycle2.components.support.RxFragment;

import org.changs.aplug.interf.OnBackPressedListener;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.support.AndroidSupportInjection;
import dagger.android.support.HasSupportFragmentInjector;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by yincs on 2017/7/22.
 */

public abstract class BaseFragment extends RxFragment
        implements IView, HasSupportFragmentInjector {

    private BaseActivity activity;
    private View rootView;
    private List<Runnable> mOptAfterCreated;

    @Inject DispatchingAndroidInjector<Fragment> childFragmentInjector;

    @Override
    public AndroidInjector<Fragment> supportFragmentInjector() {
        return childFragmentInjector;
    }


    public void execute(Runnable opt) {
        final View rootView = getRootView();
        if (rootView == null) {
            if (mOptAfterCreated == null) mOptAfterCreated = new ArrayList<>();
            mOptAfterCreated.add(opt);
        } else {
            opt.run();
        }
    }

    private void executeOptAfterCreated() {
        if (mOptAfterCreated == null) return;
        for (Runnable runnable : mOptAfterCreated) {
            runnable.run();
        }
        mOptAfterCreated.clear();
        mOptAfterCreated = null;
    }

    @Override
    public void onAttach(Context context) {
        AndroidSupportInjection.inject(this);
        super.onAttach(context);
        activity = (BaseActivity) context;
    }

    @Override
    public IDialogOpt showLoading() {
        return activity.showLoading();
    }

    @Override
    public void hideLoading() {
        activity.hideLoading();
    }

    @Override
    public void onError(@StringRes int resId) {
        activity.onError(resId);
    }

    @Override
    public void onError(String message) {
        activity.onError(message);
    }

    @Override
    public void showMessage(String message) {
        activity.showMessage(message);
    }

    @Override
    public void showMessage(@StringRes int resId) {
        activity.showMessage(resId);
    }

    @Override
    public <T> ObservableTransformer<T, T> bindUntilDestroy(boolean threadSwitch) {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply(Observable<T> observable) {
                return observable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .compose(BaseFragment.this.<T>bindUntilEvent(FragmentEvent.DESTROY));
            }
        };
    }

    @Override
    public BaseActivity getContext() {
        return activity;
    }


    @Override
    public void onResume() {
        super.onResume();
        if (this instanceof OnBackPressedListener) {
            getContext().setOnBackPressedListener((OnBackPressedListener) this);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (this instanceof OnBackPressedListener && this == getContext().getOnBackPressedListener()) {
            getContext().setOnBackPressedListener(null);
        }
    }

    public final void hide() {
        getFragmentManager()
                .beginTransaction()
                .hide(this)
                .commitAllowingStateLoss();
    }

    public final void show() {
        getFragmentManager()
                .beginTransaction()
                .show(this)
                .commitAllowingStateLoss();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = setup(inflater, container, savedInstanceState);
        executeOptAfterCreated();
        return rootView;
    }

    public View getRootView() {
        return rootView;
    }

    public String getTitle() {
        return null;
    }

    @SuppressWarnings("unchecked")
    public <T extends View> T findViewById(int id) {
        if (rootView == null) return null;
        return (T) rootView.findViewById(id);
    }

    public abstract View setup(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);

}
